import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
import { RouteConfig } from 'vue-router'
import { asyncRoutes, constantRoutes, developmentRoutes } from '@/router'
import store from '@/store'
import settings from '@/settings'

const hasPermission = (roles: string[], route: RouteConfig) => {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta?.roles.includes(role))
  } else {
    return true
  }
}

export const filterAsyncRoutes = (routes: RouteConfig[], roles: string[]) => {
  const res: RouteConfig[] = []
  routes.forEach(route => {
    const r = { ...route }
    if (hasPermission(roles, r)) {
      if (r.children) {
        r.children = filterAsyncRoutes(r.children, roles)
      }
      res.push(r)
    }
  })
  return res
}

export interface IPermissionState {
    routes: RouteConfig[]
    dynamicRoutes: RouteConfig[]
}

@Module({ dynamic: true, store, name: 'permission' })
class Permission extends VuexModule implements IPermissionState {
    public routes: RouteConfig[] = []
    public dynamicRoutes: RouteConfig[] = []

    @Mutation
    private SET_ROUTES(routes: RouteConfig[]) {
      this.routes = constantRoutes.concat(routes)
      this.dynamicRoutes = routes
    }

    @Action({ rawError: true })
    public GenerateRoutes(params: { roles: string[], routes: RouteConfig[] }) {
      const _routes = params.routes ? params.routes : []
      const roles = params.roles ? params.roles : []
      let accessedRoutes
      const dpRoutes = process.env.NODE_ENV === 'development' && settings.showDevelopMenu ? developmentRoutes : []
      const allRoutes = [..._routes, ...dpRoutes, ...asyncRoutes]
      if (roles.includes('admin')) {
        accessedRoutes = allRoutes
      } else {
        accessedRoutes = filterAsyncRoutes(allRoutes, roles)
      }
      this.SET_ROUTES(accessedRoutes)
    }
}

export const PermissionModule = getModule(Permission)
